package dlally.model;

import java.util.Arrays;

import junit.framework.TestCase;
/**
 * Tests the construction and all the methods in the DecisionLinesEvent
 * @author Douglas Lally (dlally@wpi.edu)
 *
 */
public class testDecisionLinesEvent extends TestCase {
	/**
	 * This test requires a DecisionLinesEvent
	 */
	DecisionLinesEvent myEvent;

	/**
	 * Construct a dummy event to use for testing
	 */
	protected void setUp() throws Exception {
		super.setUp();
		myEvent = new DecisionLinesEvent(5,5);
	}

	protected void tearDown() throws Exception {
		super.tearDown();
	}
	/**
	 * Tests adding edges, to make sure that invalid ones are rejected, and appropriate ones are allowed.
	 * Note that running this test will cause many error messages to print to console, this is normal and to be expected.
	 * Each invalid edge should generate one error message.
	 */
	public void testAddingEdges(){
		Edge invalidEdge = new Edge(-1,0,10);
		Edge invalidEdge2 = new Edge(4,5,10);
		Edge edge1 = new Edge(0,1,9);
		Edge edge2 = new Edge(1,2,15);
		Edge edge3 = new Edge(2,3,21);
		Edge nullEdge = null;
		Edge edge4 = new Edge(0,1,50);
		Edge edge5 = new Edge(3,4,20);
		assertFalse(myEvent.addEdge(nullEdge));
		assertFalse(myEvent.addEdge(invalidEdge));
		assertFalse(myEvent.addEdge(invalidEdge2));
		assertTrue(myEvent.addEdge(edge2));
		assertFalse(myEvent.addEdge(edge1));
		assertFalse(myEvent.addEdge(edge3));
		assertTrue(myEvent.addEdge(edge4));
		assertTrue(myEvent.addEdge(edge5));
	}
	
	/**
	 * Tests setting choices, both to valid and invalid options
	 * Again, this test will print an error messages to the console. This is normal, and to be expected
	 */
	public void testValidChoice(){
		assertFalse(myEvent.setChoice(0, null));
		assertFalse(myEvent.setChoice(0, ""));
		assertFalse(myEvent.setChoice(-1, "tooFarLeft"));
		assertFalse(myEvent.setChoice(5, "tooFarRight"));
		assertTrue(myEvent.setChoice(0, "left"));
		assertTrue(myEvent.setChoice(4,"right"));
		assertFalse(myEvent.setChoice(3,"left"));
		assertFalse(myEvent.setChoice(2, "rIgHt"));
	}
	/**
	 * Tests the isDone method, making sure that it is only true once numPlayers*numRounds edges have been added
	 */
	public void testIsDone(){
		// The main method would generally prevent an event this small, however the logic will still hold
		DecisionLinesEvent myShortEvent = new DecisionLinesEvent(2,3);
		assertFalse(myShortEvent.isDone());
		myShortEvent.addEdge(new Edge(0,1,10));
		assertFalse(myShortEvent.isDone());
		myShortEvent.addEdge(new Edge(0,1,20));
		assertFalse(myShortEvent.isDone());
		myShortEvent.addEdge(new Edge(1,2,30));
		assertFalse(myShortEvent.isDone());
		myShortEvent.addEdge(new Edge(1,2,40));
		assertFalse(myShortEvent.isDone());
		myShortEvent.addEdge(new Edge(0,1,50));
		assertFalse(myShortEvent.isDone());
		myShortEvent.addEdge(new Edge(0,1,60));
		assertTrue(myShortEvent.isDone());
	}
	/**
	 * Quick test of the get methods
	 */
	public void testGets(){
		assertEquals(myEvent.getNumRounds(),5);
	}
	/**
	 * Test of the prioritizedChoices method, both for a game that has no edges, and for one that has 6.
	 * I have run additional tests by playing the game, and the logic of the prioritizedChoices method does hold for larger numbers
	 */
	public void testPrioritizedChoices(){
		// First test a simple case with no added edges
		DecisionLinesEvent mydle = new DecisionLinesEvent(2,3);
		mydle.setChoice(0, "first");
		mydle.setChoice(1, "second");
		mydle.setChoice(2, "third");
		String[] arr2 = {"first","second","third"};
		assertTrue(isSameStringArray(mydle.prioritizedChoices(), arr2));
		// Now test a finished event with 6 edges
		mydle.addEdge(new Edge(0,1,0));
		mydle.addEdge(new Edge(1,2,10));
		mydle.addEdge(new Edge(0,1,20));
		mydle.addEdge(new Edge(1,2,30));
		mydle.addEdge(new Edge(1,2,40));
		mydle.addEdge(new Edge(1,2,50));
		String[] arr3 = {"third","first","second"};
		System.out.println(Arrays.toString(mydle.prioritizedChoices()));
		assertTrue(isSameStringArray(mydle.prioritizedChoices(), arr3));
		
	}
	/**
	 * Helper function to compare two arrays of strings by comparing the ith element of each array to the ith element of the other
	 * @param arr1 first array to examine
	 * @param arr2 second array to examine
	 * @return true if the arrays contain the same strings in the same order, false otherwise
	 */
	static boolean isSameStringArray(String[] arr1, String[] arr2){
		if(arr1.length != arr2.length)
			return false;
		for(int i = 0; i < arr1.length; i++){
			if(arr1[i] == null || arr2[i] == null)
				return false;
			if(arr1[i].compareToIgnoreCase(arr2[i]) != 0)
				return false;
		}
		return true;
	}

}
